#include "led188.h"

#define LED_SEG_B1 34
#define LED_SEG_C1 24

#define LED_SEG_A2 23
#define LED_SEG_B2 32
#define LED_SEG_C2 43
#define LED_SEG_D2 42
#define LED_SEG_E2 52
#define LED_SEG_F2 53
#define LED_SEG_G2 54

#define LED_SEG_A3 12
#define LED_SEG_B3 21
#define LED_SEG_C3 13
#define LED_SEG_D3 31
#define LED_SEG_E3 14
#define LED_SEG_F3 41
#define LED_SEG_G3 51

#define LED_SEG_K1 35
#define LED_SEG_K2 25

code uint8_t segNumArray[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};

//bitMap
//v1:百 v2:十 v3:个位
// B1->BIT0
// K2->BIT17
code uint8_t segAllPairMask [] = {
	0,
	LED_SEG_B1,
	LED_SEG_C1,
	0,
	0,
	0,
	0,
	
	//INDEX LED_SEG_MAX 
	LED_SEG_A2, 
	LED_SEG_B2, 
	LED_SEG_C2, 
	LED_SEG_D2, 
	LED_SEG_E2, 
	LED_SEG_F2, 
	LED_SEG_G2,

	LED_SEG_A3, 
	LED_SEG_B3, 
	LED_SEG_C3, 
	LED_SEG_D3, 
	LED_SEG_E3, 
	LED_SEG_F3, 
	LED_SEG_G3,

	LED_SEG_K1,
	LED_SEG_K2, //index 22
};

static void LEDSegNoneDisplay(Led188Dev_t *dev)
{
	SOC_GpioInitExt(dev->p1, S_GPIO_Mode_Out_OD);
	SOC_GpioInitExt(dev->p2, S_GPIO_Mode_Out_OD);
	SOC_GpioInitExt(dev->p3, S_GPIO_Mode_Out_OD);
	SOC_GpioInitExt(dev->p4, S_GPIO_Mode_Out_OD);
	SOC_GpioInitExt(dev->p5, S_GPIO_Mode_Out_OD);
	
	SOC_GpioWriteExt(dev->p1, 1);
	SOC_GpioWriteExt(dev->p2, 1);
	SOC_GpioWriteExt(dev->p3, 1);
	SOC_GpioWriteExt(dev->p4, 1);
	SOC_GpioWriteExt(dev->p5, 1);
}

static uint16_t __GetPortPin(Led188Dev_t *dev, int id)
{
	switch(id)
	{
		case 1:
		return dev->p1;
		case 2:
		return dev->p2;
		case 3:
		return dev->p3;
		case 4:
		return dev->p4;
		case 5:
		return dev->p5;
		default:
		return 0;
	}
}

static void LEDSegDisplay(Led188Dev_t *dev, uint8_t mask)
{
	uint16_t ph;
	uint16_t pl;

	if(mask == 0)
		return;

	//恢复默认
	// LEDSegNoneDisplay(dev);
	ph = __GetPortPin(dev, mask / 10);
	pl = __GetPortPin(dev, mask % 10);

	//显示
	SOC_GpioInitExt(ph, S_GPIO_Mode_Out_PP); 
	SOC_GpioInitExt(pl, S_GPIO_Mode_Out_PP); 
	SOC_GpioWriteExt(ph, 1); 
	SOC_GpioWriteExt(pl, 0);
}

#if LED188_BITMAP_VIRTUAL_MODE_EN > 0
static void LedDisplayToBitMap(Led188Dev_t *dev)
{
	uint8_t v1 = dev->val / 100;
	uint8_t v2 = dev->val / 10 % 10;
	uint8_t v3 = dev->val % 10;
	uint32_t bitValTemp = 0;

	if(dev->showZero || dev->val > 100)
		bitValTemp |= ((uint32_t)segNumArray[v1] << 0);

	if(dev->showZero || dev->val > 10)
		bitValTemp |= ((uint32_t)segNumArray[v2] << LED_SEG_MAX);
	
	bitValTemp |= ((uint32_t)segNumArray[v3] << (LED_SEG_MAX * 2));

	if(dev->showPercent)
	{
		bitValTemp |= (0x01ul << (LED_SEG_MAX * 3));
	}

	if(dev->showCharging)
	{
		bitValTemp |= (0x01ul << (LED_SEG_MAX * 3 + 1));
	}

	SOC_DisableAll_IT();
	dev->bitVal = bitValTemp;
	SOC_EnableAll_IT();
}

/// @brief 
/// @param dev 
static void LedDisplayRefreshByBitMapMode(Led188Dev_t *dev) 
{
	LEDSegNoneDisplay(dev);

	if((dev->bitVal >> dev->currentScanIndex) & 0x01)
	{
		LEDSegDisplay(dev, segAllPairMask[dev->currentScanIndex]);
	}
}

#else

static void LedDisplayOneNum(Led188Dev_t *dev, uint8_t num)
{
	uint8_t segNum;

	if(num > 9)
		return;

	segNum = segNumArray[num];
	if((segNum & (0x01 << (dev->currentScanIndex % LED_SEG_MAX))) != 0)
	{
		LEDSegDisplay(dev, segAllPairMask[dev->currentScanIndex]);
	}
}

/// @brief 
/// @param dev 
static void LedDisplayRefresh(Led188Dev_t *dev)
{
	uint8_t segNum;
	uint8_t index;

	LEDSegNoneDisplay(dev);
	if(dev->currentScanIndex < LED_SEG_MAX)
	{	
		if(dev->showZero || dev->val >= 100)
			LedDisplayOneNum(dev, dev->v1);
	}
	else if(dev->currentScanIndex < (LED_SEG_MAX * 2))
	{	
		if(dev->showZero || dev->val >= 10)
			LedDisplayOneNum(dev, dev->v2);
	}
	else if(dev->currentScanIndex < (LED_SEG_MAX * 3))
	{
		LedDisplayOneNum(dev, dev->v3);
	}
	else if(dev->currentScanIndex == ((LED_SEG_MAX * 3)))
	{
		if(dev->showCharging)
			LEDSegDisplay(dev, segAllPairMask[dev->currentScanIndex]);
	}
	else if(dev->currentScanIndex == ((LED_SEG_MAX * 3) + 1))
	{
		if(dev->showPercent)
			LEDSegDisplay(dev, segAllPairMask[dev->currentScanIndex]);
	}
}
#endif 

void LED188Init(Led188Dev_t *dev)
{
	dev->showPercent = true;
	dev->showCharging = true;
	dev->showZero = false;

	dev->currentScanIndex = 0;

#if LED188_BITMAP_VIRTUAL_MODE_EN > 0
	dev->bitVal = 0;
#endif 

	LED188SetValue(dev, 0, false, false);
}

void LED188CloseAll(Led188Dev_t *dev)
{
	LEDSegNoneDisplay(dev);
}

void LED188SetValue(Led188Dev_t *dev, uint8_t val, bool showPercent, bool showCharging)
{
    if(val > 199)
        val = 199;

    dev->val = val;
    dev->showPercent = showPercent;
    dev->showCharging = showCharging;

#if LED188_BITMAP_VIRTUAL_MODE_EN  > 0
	//to bitVal
	LedDisplayToBitMap(dev);
#else 
	SOC_DisableAll_IT();
	dev->v1 = dev->val / 100;
	dev->v2 = dev->val / 10 % 10;
	dev->v3 = dev->val % 10;
	SOC_EnableAll_IT();
#endif 
}

void LED188Update(Led188Dev_t *dev)
{
#if LED188_BITMAP_VIRTUAL_MODE_EN == 1
	LedDisplayRefreshByBitMapMode(dev);
#else 
	LedDisplayRefresh(dev);
#endif 

	do
	{
		dev->currentScanIndex = (dev->currentScanIndex + 1) % sizeof(segAllPairMask);
	}while (segAllPairMask[dev->currentScanIndex] == 0);
}

void LED188Test(Led188Dev_t *dev, uint32_t ms)
{	
	int len = sizeof(segAllPairMask) / sizeof(uint8_t);
	int i;

	for(i = 0; i < len; i++)
	{
		if(segAllPairMask[i] == 0)
			continue;

		LEDSegNoneDisplay(dev);
		LEDSegDisplay(dev, segAllPairMask[i]);
		SOC_Delay(ms);
	}
}
